#include <Arduino.h>

// led管
#define LED2 2
// 1. 呼吸灯 pwd模式
#define LED22 22
// 2.  呼吸灯 analog
#define LED23 23
// 3. 呼吸灯 dac转换，仅有25,26引脚
#define LED26 26

// PWM占空比方波
#define PWM_CHAN 0   // 使用的PWM通道号
#define BIT_WIDTH 10 // 设置的PWM位宽 则最大分辨为 2^10-1
#define FREQ 1000    // 设置的PWM频率

// 串口通信
int count = 0;

// 1. 占空比呼吸灯
void PWMBreathingLight(int pwdChan, int max, int second);
// 2. analog呼吸灯
void analogWriteLight(int ledPin, int max, int second);
// 3. 数模转换呼吸灯
void dacLight(int ledPin);

void setup()
{
  // 串口通信 - 与电脑
  Serial.begin(115200);
  pinMode(LED2, OUTPUT);
  pinMode(LED23, OUTPUT);

  ledcSetup(PWM_CHAN, FREQ, BIT_WIDTH);
  ledcAttachPin(LED22, PWM_CHAN);
}

void loop()
{
  // 1. 点亮
  digitalWrite(LED2, 1);
  delay(50);

  // 2. 呼吸灯 - 使用 leds 函数
  //  最大值  2^10-1 = 1023
  int max = pow(2, BIT_WIDTH) - 1;
  PWMBreathingLight(PWM_CHAN, max, 1);

  // 3. 呼吸灯 - 使用analog
  analogWriteLight(LED23, 255, 1);

  // 4. 呼吸灯 - 使用dac
  dacLight(LED26);

  // 4. 关闭
  digitalWrite(LED2, 0);
  delay(1000);

  // 5. 写入监视器
  count++;
  Serial.printf("循环次数%d \n", count);
}
// 占空比呼吸灯
void PWMBreathingLight(int pwdChan, int max, int second)
{
  int duration = second * 1000.0 / float(max);
  if (duration < 1)
  {
    duration = 1;
  }

  // 占空比从0到1023，逐渐变大，每次中间延迟1ms，不然程序运行太快眼睛无法查看效果
  for (int i = 0; i <= max; i++)
  {
    ledcWrite(PWM_CHAN, i);
    delay(duration);
  }

  // 占空比从1023到0，逐渐变小
  for (int i = max; i >= 0; i--)
  {
    ledcWrite(PWM_CHAN, i);
    delay(duration);
  }
}

// analogWrite呼吸灯
void analogWriteLight(int ledPin, int max, int second)
{
  int duration = second * 1000.0 / float(max);
  int top = max * 4.0 / 5.0;

  // 呼吸亮
  for (int i = 0; i <= max; i++)
  {
    analogWrite(ledPin, i);
    if (i > top)
    {
      int tmp = duration * 2;
      delay(tmp);
    }
    else
    {
      delay(duration);
    }
  }
  // 呼吸灭
  for (int i = max; i >= 0; i--)
  {
    analogWrite(ledPin, i);
    delay(duration);
  }
}

// 数模转换呼吸灯，真实的电压
void dacLight(int ledPin)
{
  for (int i = 0; i <= 255; i++) // 依次增大输出电压
  {
    dacWrite(ledPin, i);
    delay(5);
  }
  for (int i = 255; i >= 0; i--) // 依次减小输出电压
  {
    dacWrite(ledPin, i);
    delay(5);
  }
}
